package com.fy.util;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import jp.sourceforge.qrcode.QRCodeDecoder;
import jp.sourceforge.qrcode.data.QRCodeImage;
import com.swetake.util.Qrcode;

/**
 * 二维码编码及解码工具类（使用Qrcode.jar）
 * @author 小叶
 * @date 2016年2月22日
 * @version 2.0
 */
public class QrcodeUtil {
	static String dir = System.getProperty("user.dir");
	public static void main(String[] args) {
		// 本地生成二维码
		String content = "大家好，我是叶权瑞";
		String imgPath = dir + "/WebRoot/img/yqr.png";
		String frontPath = dir + "/WebRoot/img/front.png";
		encodeQrcode(content, imgPath, frontPath);
		decodeQrcode(imgPath);
	}
	/**
	 * 生成二维码
	 * @param content 需要生成的内容
	 * @param imgPath 生成二维码图片的路径
	 * @param frontPath 前置图片的路径
	 */
	public static void encodeQrcode(String content, String imgPath, String frontPath) {
		int width = 235, height = 235;
		try {
			Qrcode qrcode = new Qrcode();// 实例化Qrcode对象
			qrcode.setQrcodeErrorCorrect('M');// 设置二维码排错率，可选L(7%)、M(15%)、Q(25%)、H(30%)
			qrcode.setQrcodeEncodeMode('B');// 设置二维码编码模式为二进制编码
			qrcode.setQrcodeVersion(15);// 设置二维码尺寸，取值范围[1-40]，版本详细信息：http://www.qrcode.com/zh/about/version.html
			BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);// 初始化图片
			Graphics2D grap = image.createGraphics();// 创建图层
			grap.setBackground(Color.white);// 设置背景颜色为白色
			grap.clearRect(0, 0, width, height);// 清空内容，创建一个二维码的矩形区域
			grap.setColor(Color.black);// 设置画笔颜色
			byte[] contentBytes = content.getBytes("utf-8");// 获取内容字节数组，设置编码集
			if (contentBytes.length > 0 && contentBytes.length < 1784) {
				boolean[][] codeOut = qrcode.calQrcode(contentBytes);// 传递内容字节数组，调用calQrcode方法方茴二维布尔型数组
				int pixoff = 2;// 设置偏移量，不设置可能导致解析出错
				// 生成二维码
				for (int i = 0; i < codeOut.length; i++)
					for (int j = 0; j < codeOut.length; j++)
						if (codeOut[j][i])// 如果为true则需要画，false则不需要
							grap.fillRect(j * 3 + pixoff, i * 3 + pixoff, 3, 3);
			} else
				System.err.println("本次二维码长度：" + contentBytes.length + "，超出版本范围[0, 1784 ]");
			File front = new File(frontPath);// 初始化前置图片文件
			if (front.isFile() && front.exists()) {// 如果文件存在执行以下操作
				BufferedImage frontImage = ImageIO.read(front);// 读取前置图片
				grap.drawImage(frontImage, 92, 92, 50, 50, null);// 将前置图片添加到二维码上
			} else
				System.err.println("前置图片不存在，默认不添加，二维码继续生成……");
			grap.dispose();// 释放此图形的上下文以及它使用的所有系统资源，之后不能再使用Graphics对象
			image.flush();// 刷新此Image对象正在使用的所有可重构的资源
			ImageIO.write(image, "png", new File(imgPath));// 根据路径生成二维码图片
			System.out.println("生成二维码成功，图片在：" + imgPath);
		} catch (Exception e) {
			System.err.println("生成二维码失败：" + e.getMessage());
			e.printStackTrace();
		}
	}
	/**
	 * 解析二维码
	 * @param imgPath 需要解析的二维码图片路径
	 * @return String 二维码解析后的内容
	 */
	public static String decodeQrcode(String imgPath) {
		// QRCode 二维码图片的文件
		File imageFile = new File(imgPath);
		BufferedImage image = null;
		String decodedData = null;
		try {
			image = ImageIO.read(imageFile);
			QRCodeDecoder decoder = new QRCodeDecoder();
			decodedData = new String(decoder.decode(new JavaImage(image)), "utf-8");
			System.out.println("解析二维码成功，结果是：" + decodedData);
		} catch (Exception e) {
			System.err.println("解析二维码失败：" + e.getMessage());
			e.printStackTrace();
		}
		return decodedData;
	}
}

/**
 * 新建JavaImage类实现QRCodeImage接口
 * @author 小叶
 * @date 2016年2月22日
 * @version 1.0
 */
class JavaImage implements QRCodeImage {
	BufferedImage image;
	public JavaImage(BufferedImage image) {
		this.image = image;
	}
	@Override
	public int getWidth() {
		return image.getWidth();
	}
	@Override
	public int getHeight() {
		return image.getHeight();
	}
	@Override
	public int getPixel(int x, int y) {
		return image.getRGB(x, y);
	}
}